(in-package :graph-model)

(defvar *plus-infinity*)
(defvar *minus-infinity*)
(setf *plus-infinity*  '+infty)
(setf *minus-infinity* '-infty)

(defgeneric weigth (o))
(defgeneric weigth= (o1 o2))
(defgeneric weigth<= (o1 o2))
(defgeneric weigth>= (o1 o2))
(defgeneric weigth< (o1 o2))
(defgeneric weigth> (o1 o2))

(defgeneric change-weight (o newweigth))

(defclass weight-mixin ()
  ((weight :initarg :weight :accessor weight :initform nil)))

(defmethod print-object ((o weight-mixin) stream)
  (when (weight o)
    (format stream "~A" (weight o))))

(defmethod change-weight ((o weight-mixin) newweight)
  (setf (slot-value o 'weight) newweight))

(defmethod weight ((o t))
   nil)

(defmethod weight ((l list))
  (loop for e in l
	sum (weight e)))
  
(defmethod weight<= ((w1 integer) (w2 integer)) (<= w1 w2))
(defmethod weight<= (w1 (w2 (eql *plus-infinity*))) t)
(defmethod weight<= ((w1 (eql *minus-infinity*)) w2) t)

(defmethod weight= ((w1 (eql *minus-infinity*)) (a2 (eql *plus-infinity*))) nil)
(defmethod weight= (w1 w2) (eq w1 w2))
(defmethod weight= ((w1 integer) (w2 integer)) (= w1 w2))

(defmethod weight/= (w1 w2) (not (weight= w1 w2)))

(defmethod weight< (w1 w2)
  (and
   (weight/= w1 w2)
   (weight<= w1 w2)))

(defmethod weight> (w1 w2) (not (weight<= w1 w2)))
(defmethod weight>= (w1 w2) (or (weight= w1 w2) (weight> w1 w2)))

(defun min-weight (w1 w2)
  (if (weight< w1 w2)
      w1
      w2))

(defmethod weight+ ((w1 integer) (w2 (eql *plus-infinity*)))
  *plus-infinity*)

(defmethod weight+ ((w1 (eql *plus-infinity*)) (w2 integer))
  *plus-infinity*)

(defmethod weight+ ((w1 integer) (w2 integer))
  (+ w1 w2))

(defmethod compare-objects-weight ((o1 weight-mixin) (o2 weight-mixin))
  (weight< (weight o1) (weight o2)))
